{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.metrics import classification_report\n",
    "from sklearn.metrics import confusion_matrix\n",
    "\n",
    "from matplotlib import pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 读取数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "#读取数据\n",
    "#dpath = './data/'\n",
    "train1 = pd.read_csv('Otto_FE_train_org.csv')\n",
    "train2 = pd.read_csv('Otto_FE_train_tfidf.csv')\n",
    "\n",
    "#去掉id\n",
    "train2 = train2.drop(['id','target'],axis=1)\n",
    "train = pd.concat([train1,train2],axis=1,ignore_index=False)\n",
    "\n",
    "del train1\n",
    "del train2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>feat_1</th>\n",
       "      <th>feat_2</th>\n",
       "      <th>feat_3</th>\n",
       "      <th>feat_4</th>\n",
       "      <th>feat_5</th>\n",
       "      <th>feat_6</th>\n",
       "      <th>feat_7</th>\n",
       "      <th>feat_8</th>\n",
       "      <th>feat_9</th>\n",
       "      <th>...</th>\n",
       "      <th>feat_84_tfidf</th>\n",
       "      <th>feat_85_tfidf</th>\n",
       "      <th>feat_86_tfidf</th>\n",
       "      <th>feat_87_tfidf</th>\n",
       "      <th>feat_88_tfidf</th>\n",
       "      <th>feat_89_tfidf</th>\n",
       "      <th>feat_90_tfidf</th>\n",
       "      <th>feat_91_tfidf</th>\n",
       "      <th>feat_92_tfidf</th>\n",
       "      <th>feat_93_tfidf</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>0.016393</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.075886</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.013158</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.013158</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>0.016393</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.014286</td>\n",
       "      <td>0.315789</td>\n",
       "      <td>0.1</td>\n",
       "      <td>0.131579</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.460983</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.008244</td>\n",
       "      <td>0.022456</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>...</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.124622</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.145988</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 188 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   id    feat_1  feat_2  feat_3    feat_4    feat_5  feat_6    feat_7  \\\n",
       "0   1  0.016393     0.0     0.0  0.000000  0.000000     0.0  0.000000   \n",
       "1   2  0.000000     0.0     0.0  0.000000  0.000000     0.0  0.000000   \n",
       "2   3  0.000000     0.0     0.0  0.000000  0.000000     0.0  0.000000   \n",
       "3   4  0.016393     0.0     0.0  0.014286  0.315789     0.1  0.131579   \n",
       "4   5  0.000000     0.0     0.0  0.000000  0.000000     0.0  0.000000   \n",
       "\n",
       "     feat_8  feat_9      ...        feat_84_tfidf  feat_85_tfidf  \\\n",
       "0  0.000000     0.0      ...             0.000000       0.075886   \n",
       "1  0.013158     0.0      ...             0.000000       0.000000   \n",
       "2  0.013158     0.0      ...             0.000000       0.000000   \n",
       "3  0.000000     0.0      ...             0.460983       0.000000   \n",
       "4  0.000000     0.0      ...             0.000000       0.124622   \n",
       "\n",
       "   feat_86_tfidf  feat_87_tfidf  feat_88_tfidf  feat_89_tfidf  feat_90_tfidf  \\\n",
       "0       0.000000       0.000000            0.0            0.0       0.000000   \n",
       "1       0.000000       0.000000            0.0            0.0       0.000000   \n",
       "2       0.000000       0.000000            0.0            0.0       0.000000   \n",
       "3       0.008244       0.022456            0.0            0.0       0.000000   \n",
       "4       0.000000       0.000000            0.0            0.0       0.145988   \n",
       "\n",
       "   feat_91_tfidf  feat_92_tfidf  feat_93_tfidf  \n",
       "0            0.0            0.0            0.0  \n",
       "1            0.0            0.0            0.0  \n",
       "2            0.0            0.0            0.0  \n",
       "3            0.0            0.0            0.0  \n",
       "4            0.0            0.0            0.0  \n",
       "\n",
       "[5 rows x 188 columns]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 准备数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_train = train['target']\n",
    "X_train = train.drop(['id','target'],axis=1)\n",
    "\n",
    "feat_names = X_train.columns\n",
    "\n",
    "from scipy.sparse import csr_matrix\n",
    "X_train = csr_matrix(X_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(49502, 186)\n"
     ]
    }
   ],
   "source": [
    "#利用train_test_split分割测试集和训练集\n",
    "from sklearn.model_selection import train_test_split\n",
    "X_train_part,X_test_part,y_train_part,y_test_part = train_test_split(X_train,y_train,train_size=0.8,test_size=0.2,random_state=0)\n",
    "\n",
    "print(X_train_part.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 模型训练"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 默认参数的SVC"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.svm import LinearSVC"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,\n",
       "     intercept_scaling=1, loss='squared_hinge', max_iter=1000,\n",
       "     multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,\n",
       "     verbose=0)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#1、生成学习器实例\n",
    "SVC1 = LinearSVC()\n",
    "#2、模型训练\n",
    "SVC1.fit(X_train_part,y_train_part)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy is: 0.7643018745959922\n",
      "Classification report for classifier LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,\n",
      "     intercept_scaling=1, loss='squared_hinge', max_iter=1000,\n",
      "     multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,\n",
      "     verbose=0):\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "     Class_1       0.59      0.35      0.44       370\n",
      "     Class_2       0.65      0.86      0.74      3205\n",
      "     Class_3       0.52      0.35      0.41      1546\n",
      "     Class_4       0.76      0.15      0.25       566\n",
      "     Class_5       0.95      0.96      0.95       542\n",
      "     Class_6       0.93      0.92      0.93      2823\n",
      "     Class_7       0.69      0.62      0.66       572\n",
      "     Class_8       0.86      0.92      0.89      1703\n",
      "     Class_9       0.83      0.85      0.84      1049\n",
      "\n",
      "   micro avg       0.76      0.76      0.76     12376\n",
      "   macro avg       0.75      0.67      0.68     12376\n",
      "weighted avg       0.76      0.76      0.75     12376\n",
      "\n",
      "\n",
      "Confusion matrix:\n",
      "[[ 129   16    3    0    1   41   10   77   93]\n",
      " [   3 2762  361   10   12   12   23   14    8]\n",
      " [   1  943  535    8    2    2   40    7    8]\n",
      " [   0  343   88   86    5   25   15    3    1]\n",
      " [   0   17    1    0  519    1    0    3    1]\n",
      " [  22   32    5    6    1 2609   46   54   48]\n",
      " [  16   71   35    1    3   42  357   41    6]\n",
      " [  19   24    7    0    4   42   17 1569   21]\n",
      " [  27   20    3    2    2   37   10   55  893]]\n"
     ]
    }
   ],
   "source": [
    "#在校验集上测试模型性能\n",
    "y_predict = SVC1.predict(X_test_part)\n",
    "\n",
    "print('accuracy is:',accuracy_score(y_test_part,y_predict))\n",
    "print('Classification report for classifier %s:\\n%s\\n' % (SVC1,classification_report(y_test_part,y_predict)))\n",
    "print('Confusion matrix:\\n%s' % confusion_matrix(y_test_part,y_predict))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 线性SVM正则参数调优"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "只对C进行参数调优"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fit_grid_point_Linear1(C,X_train,y_train,X_test,y_test):\n",
    "    #在训练集上训练SVC模型\n",
    "    SVC2 = LinearSVC(C = C)\n",
    "    SVC2 = SVC2.fit(X_train,y_train)\n",
    "    #print(SVC2)\n",
    "    #在校验集上返回accuracy\n",
    "    accuracy=[0,0]\n",
    "    accuracy[0] = SVC2.score(X_train,y_train)\n",
    "    accuracy[1] = SVC2.score(X_test,y_test)\n",
    "    print('C={}:accuracy_train={}:accuracy_test={}' .format(C,accuracy[0],accuracy[1]))\n",
    "    return accuracy\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C=0.1:accuracy_train=0.7643125530281605:accuracy_test=0.758322559793148\n",
      "C=1.0:accuracy_train=0.7712415659973334:accuracy_test=0.7643018745959922\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/anaconda3/lib/python3.7/site-packages/sklearn/svm/base.py:922: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.\n",
      "  \"the number of iterations.\", ConvergenceWarning)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C=10.0:accuracy_train=0.773120277968567:accuracy_test=0.7656755009696187\n",
      "C=100.0:accuracy_train=0.7728576623166741:accuracy_test=0.7668067226890757\n",
      "C=1000.0:accuracy_train=0.66938709547089:accuracy_test=0.6603910795087266\n"
     ]
    }
   ],
   "source": [
    "C_s = np.logspace(-1, 3, 5)# logspace(a,b,N)把10的a次方到10的b次方区间分成N份  \n",
    "#penalty_s = ['l1','l2']\n",
    "#print(C_s)\n",
    "#[1.e-01 1.e+00 1.e+01 1.e+02 1.e+03]\n",
    "accuracy_train = []\n",
    "accuracy_test = []\n",
    "for i,oneC in enumerate(C_s):\n",
    "    tmp = fit_grid_point_Linear1(oneC,X_train_part,y_train_part,X_test_part,y_test_part)\n",
    "    accuracy_train.append(tmp[0])\n",
    "    accuracy_test.append(tmp[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'accuracy')"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "x_axis = np.log10(C_s)\n",
    "plt.plot(x_axis,np.array(accuracy_train), 'b-',label='train')\n",
    "plt.plot(x_axis,np.array(accuracy_test), 'r-',label='test')\n",
    "plt.legend()\n",
    "plt.xlabel( 'log(C)' )                                                                                                      \n",
    "plt.ylabel( 'accuracy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best_C_train=10.0,Best_C_test=100.0\n"
     ]
    }
   ],
   "source": [
    "#最佳超参数\n",
    "index_train = np.argmax(accuracy_train,axis=None)\n",
    "index_test = np.argmax(accuracy_test,axis=None)\n",
    "Best_C_train = C_s[index_train]\n",
    "Best_C_test = C_s[index_test]\n",
    "print('Best_C_train={},Best_C_test={}' .format(Best_C_train,Best_C_test))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "从训练结果和测试结果可以看出准确率随C的增大而增大，当C=100时准确率最高，超过10时准确率开始下降\n",
    "因此可以得知C的最佳超参数值为100"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对C和penalty一起进行调优"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fit_grid_point_Linear2(C,penalty,X_train,y_train,X_test,y_test):\n",
    "    #在训练集上训练SVC模型\n",
    "    SVC2 = LinearSVC(C = C,penalty=penalty,dual=False)\n",
    "    SVC2 = SVC2.fit(X_train,y_train)\n",
    "    #在校验集上返回accuracy\n",
    "    accuracy=[0,0]\n",
    "    accuracy[0] = SVC2.score(X_train,y_train)\n",
    "    accuracy[1] = SVC2.score(X_test,y_test)\n",
    "    print('C={}:penalty={}:accuracy_train={}:accuracy_test={}' .format(C,penalty,accuracy[0],accuracy[1]))\n",
    "    return accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C=0.1:penalty=l1:accuracy_train=0.7614237808573391:accuracy_test=0.7547672915319974\n",
      "C=0.1:penalty=l2:accuracy_train=0.7643327542321522:accuracy_test=0.7584033613445378\n",
      "C=1.0:penalty=l1:accuracy_train=0.7714637792412428:accuracy_test=0.7654330963154492\n",
      "C=1.0:penalty=l2:accuracy_train=0.7712415659973334:accuracy_test=0.7641402714932126\n",
      "C=10.0:penalty=l1:accuracy_train=0.7740091309442043:accuracy_test=0.7660795087265676\n",
      "C=10.0:penalty=l2:accuracy_train=0.7731606803765504:accuracy_test=0.7655946994182288\n",
      "C=100.0:penalty=l1:accuracy_train=0.7745747646559735:accuracy_test=0.7662411118293472\n",
      "C=100.0:penalty=l2:accuracy_train=0.7742717465960971:accuracy_test=0.7664027149321267\n",
      "C=1000.0:penalty=l1:accuracy_train=0.7745545634519817:accuracy_test=0.7660795087265676\n",
      "C=1000.0:penalty=l2:accuracy_train=0.7743525514120642:accuracy_test=0.7661603102779574\n"
     ]
    }
   ],
   "source": [
    "#C和penalty一起调优\n",
    "C_s = np.logspace(-1, 3, 5)# logspace(a,b,N)把10的a次方到10的b次方区间分成N份  \n",
    "penalty_s = ['l1','l2']\n",
    "#print(C_s)\n",
    "#[1.e-01 1.e+00 1.e+01 1.e+02 1.e+03]\n",
    "accuracy_l1_train = []\n",
    "accuracy_l1_test = []\n",
    "accuracy_l2_train = []\n",
    "accuracy_l2_test = []\n",
    "for i,oneC in enumerate(C_s):\n",
    "    for j, penalty in enumerate(penalty_s):\n",
    "        if penalty == 'l1':\n",
    "            tmp = fit_grid_point_Linear2(oneC,penalty,X_train_part,y_train_part,X_test_part,y_test_part)\n",
    "            accuracy_l1_train.append(tmp[0])\n",
    "            accuracy_l1_test.append(tmp[1])\n",
    "        else:\n",
    "            tmp = fit_grid_point_Linear2(oneC,penalty,X_train_part,y_train_part,X_test_part,y_test_part)\n",
    "            accuracy_l2_train.append(tmp[0])\n",
    "            accuracy_l2_test.append(tmp[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'accuracy')"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZgAAAEKCAYAAAAvlUMdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzs3Xd8FNX+//HXJwkhVCkJSjUoQUXBBEK1QFCkKk00URRseEVU8FrwXgUuV3+KBRAVv3JREUUQUBEVBYEgIiiEqiAIUgOotFAT0j6/P2YTNiFlUzb183w89sHuzJnZM5Z9c+acOUdUFWOMMaaw+RR3BYwxxpRNFjDGGGO8wgLGGGOMV1jAGGOM8QoLGGOMMV5hAWOMMcYrLGCMMcZ4hQWMMcYYr7CAMcYY4xV+xV2B4hQYGKjBwcHFXQ1jjClV1q5de1hVg3IrV64DJjg4mJiYmOKuhjHGlCoisseTcl69RSYi3URkm4jsEJGRWeyfICIbXK/fRSTOtT3CbfsGEUkQkT6ufdNEZJfbvlDXdhGRSa7v2iQiLb15bcYYY3LmtRaMiPgCbwFdgFhgjYjMV9UtaWVUdYRb+UeAMNf2aCAtOGoBO4BFbqd/UlXnZvrK7kCI69UWeNv1pzHGmGLgzRZMG2CHqu5U1URgFtA7h/JRwMwstt8KfKOqZ3L5vt7AdHX8BNQQkbr5qbgxxpiC82bA1Af2uX2OdW07j4hcDDQGlmaxO5Lzg+cF122wCSJSMa/fZ4wxxvu8GTCSxbbsFp+JBOaqakqGEzgtkObAQrfNzwCXA62BWsDTefk+ERkiIjEiEnPo0KGcr8AYY0y+eTNgYoGGbp8bAAeyKZtVKwXgNuBzVU1K26CqB123wc4C7+PcivP4+1R1iqqGq2p4UFCuo+yMMcbkkzcDZg0QIiKNRcQfJ0TmZy4kIpcBNYFVWZzjvH6ZtH4VERGgD/Cra9d84G7XaLJ2wHFVPVhYF2OMMSZvvDaKTFWTRWQYzu0tX+A9Vd0sImOBGFVNC5soYJZmWrtZRIJxWiTfZzr1DBEJwrkltgH4h2v7AqAHzoizM8A9hX5RxphiowonT8KRI+e/jh6FFNcNdhHn5cl7T8t5+31xfHfTptCsWc7/zAtKMv2ulyvh4eFqD1oaU/SSkpxQyCossnsdPeoclx0RJ4SMZ55+Gl56KX/HishaVQ3PrVy5fpLfGFMwqnDqVN6C4sgROHEi+3P6+0Pt2udel1+e8XNWr5o1wS/Tr5nqucDJ7b2n5bzxPu1zaqqSkppKiqaQkppCcmoKqZqa/l5JJTnV2ZeiKaSmprrKpJDiKpd2bKqeO09KaiqppL1PIRWnbIuGl+CMl/IeCxhjDADJyXlvVRw5knOr4oILzoVAYCBcdlnuYVGlyrnbODmJT4rnj2N/8MPh39m5fSdnks6c+/F1+8FNze7HN6d9mX+kC1DW0+M020G23vG039N0vDKfTRgPWcAYU8aowunTeQ+K48ezP2eFChlDoGnT3IOiVq3zWxV5lZiSyK5ju9h+dDu/H/md7Ue2p7+PPRGb5Y+yr/jiIz74+vie997Xx/U5i/c5HZf23s/Hj4o+FfN2jjycvyB1zOm4rM5Rr1q9gv3L8YAFjDElWHIyHDuW97BITMz+nNWrZwyCkJDcw6JqVc9aFfmRkprCnuN72H7EFSJHz4XInrg9pLg9HlerUi1CaoXQKbgTIbVCCKkdQtPaTWlSqwlV/aviI7YCSUliAWNMCaEKMTEwZw58/TUcOABxcdmX9/PLGAJNmkDbtrm3KipUKLprSpOqqew/sf+8lsj2o9v54+gfJKWeu89Wzb8aIbVDaF2vNXc2vzM9SEJqhVC7cu2ir7zJNwsYY4qRKqxdC7NnO8Gye7cTHJ07O6+cwqJaNe+1KvJDVfnr9F8ZbmNtP7qd7Ue2s+PoDuKT49PLVvKrRJNaTWgW1Iw+l/VJD5CmtZtSp0odpCRdmMk3CxhjilhaqMyZ47x27XJCpUsXGDUKevd2Whol1ZEzR9KDw/2W1vYj2zmZeDK9XAWfClxa61JCaoXQ5ZIuNK3dND1I6levb7ezygELGGOKQHahcuON8NxzJS9UTpw9kWVLZPvR7RyNP5pezkd8aFyjMSG1Q7im4TXprZCQ2iE0uqARfj72E1Oe2b99Y7xEFdatO3f7yz1Unn0W+vQp3lA5k3SGHUd3ZNm5/vfpvzOUbVi9IU1rN+W2Zreld6yH1Aqhcc3G+Pv6F9MVmJLOAsaYQpQWKmktlZ07nVC54YbiCZWzyWfZeWxnlp3rsSdiM5S9qOpFhNQK4eamN2cYoXVpzUupVKFS0VXalBkWMMYUkCqsX3+upeIeKv/6lxMqtb04+Ck5NZndcbuzvKW15/geUjU1vWztSrUJqR1C58adnRBxG6FVrWI171XSlEsWMMbkQ1qozJnjBMvOneDr69z+8kaopGoq+47vy7JzfeexnSSnJqeXrV6xOiG1QmjboC13tbgrPUBCaodQq1IJ6ugxZZ4FjDEecg+VOXPgjz+cUCnMloqqsuPoDlbsXcHWw1v5/ahzW+uPY3+QkJyQXq6SXyVCaofQvE5z+l3eL8MILRvma0oKCxhjcqAKGzacu/3lHiojRzqhEhhYkPMrO4/tZNnuZUTvjmbZ7mXsP7kfAH9ffy6teSkhtUPo1qRbesd6SO0Q6lWrZ8N8TYlnAWNMJmmhknb7Ky1UOncueKioKrvjdqeHybLdy9h3Yh8AdarUISI4gk7Bneh4cUea1m6Kr49vIV6ZMUXLAsYYMobKnDmwY8e5UHn6aejbN/+hsiduT3qgRO+OZu/xvQAEVQ6iU3AnRgaPJCI4gssDL7dbW6ZM8WrAiEg34HWcFS2nqupLmfZPACJcHysDdVS1hohEABPcil4ORKrqPBGZAYQDScBq4EFVTRKRTsAXwC7XMZ+p6lgvXZopA1Rh48ZzLRX3UHnqqfyHyt7jezPc8todtxtwRnB1Cu7EUx2eolNwJ5oFNbNAMWWa1wJGRHyBt4AuQCywRkTmq+qWtDKqOsKt/CNAmGt7NBDq2l4LZxnkRa6iM4CBrvcfA/cDb7s+/6Cqvbx1Tab0cw+VOXNg+3YnVCIi8h8qsSdinUDZFc2yPcvYeWwn4Mz82/Hijjze7nE6BXfiyjpXWr+JKVe82YJpA+xQ1Z0AIjIL6A1syaZ8FDA6i+23At+o6hkAVV2QtkNEVgMNCrPSpuxRhU2bznXUu4fKE084oRIU5Pn59p/Yn95/smzPMnYc3QFAzYCadAzuyKNtHqVTcCeaX9jcAsWUa94MmPrAPrfPsUDbrAqKyMVAY2BpFrsjgfFZHFMBuAt4zG1zexHZCBwAnlDVzfmruint0kIl7fbX9u3g45O/UDl48mCGW17bj24H4IKKF9AxuCNDw4cS0TiC5nWaW6e8MW68GTBZ3VzObk3QSGCuqtvKQoCI1AWaAwuzOGYysFxVf3B9XgdcrKqnRKQHMA8IOa9SIkOAIQCNGjXy5DpMKeEeKnPmwO+/nwuVf/7TCZU6dXI/z5+n/uT73d+nB8q2I9sA5wHG6y++ngdbPUhE4wiuvvBqCxRjcuDNgIkFGrp9boDTsshKJPBwFttvAz5X1QyrfovIaCAIeDBtm6qecHu/QEQmi0igqh52P1ZVpwBTAMLDw4t2EWxT6FThl1/OtVTcQ+Xxxz0Llb9P/33ultfuZfx2+DfAWfjquouv4/6W99MpuBNhF4VZoBiTB94MmDVAiIg0BvbjhMgdmQuJyGVATWBVFueIAp7JVP5+oCtwg+q5SZZE5CLgL1VVEWkD+ABHCulaTAniHipz5sC2bU6odOrkWagcOn2I7/d8n37ba8shp1uwqn9Vrmt0HYNDB9MpuBMt67a06eaNKQCv/d+jqskiMgzn9pYv8J6qbhaRsUCMqs53FY0CZqlqhtaEiATjtIC+z3Tq/wP2AKtcQzzThiPfCjwkIslAPM6wZmuhlBGq8Ouv5zrq3UNl+HDo1y/7UDl85jDL9yxPD5Rf//4VgCoVqnBto2u5q8VdRARH0LJuSyr4FsN6wsaUUVKef4PDw8M1JiamuKthspEWKmm3v9xDZcCA7EPlaPxRlu9Znj5seNNfmwCoXKEy1zS8Jv1p+fB64RYoxuSDiKxV1fDcyln735Qo7qEyZw5s3eqESseOTkulb1+48MKMxxyLP5beQlm2Zxkb/9yIolTyq0SHhh14PuJ5OgV3onX91rY4ljFFyALGFDtV2Lz53O0v91B59FGnpeIeKscTjme45bXhzw0oSoBfAB0aduA/nf5DROMIWtdrTUW/isV3YcaUcxYwptikhcrs2edC5frrzw+V4wnH+fr3FenDhtf/uZ5UTaWib0XaN2zP6I6jiWgcQZv6bQjwCyjeizLGpLOAMUXKvaXy228g4rRUHnnECZWLLoKTZ0+yYu8Kojc5gbL24FpSNRV/X3/aNWjHc9c/R6fgTrRr0M4CxZgSzALGeF1CArzyCsycmTFUhg1zQqVqrVOs2LuCib8uI/qraNYeWEuKplDBpwJtG7Tl39f9m07BnWjfoL2tDW9MKWIBY7zuscdgypRzodLt5tPsSPyRZbuX0ffraNbsX0OKpuDn40fb+m0Zea0zfX37hu2pXKFycVffGJNPFjDGqz76CKZMUaKe+Z7GN3zHjD3LeGzaapJTk/Hz8aN1vdY8dc1TRARH0KFhB6r4VynuKhtjCokFjPGaLVtgyD9SuOj+h5lZ8R18f/QlvF44T7R/gk7Bnbim0TVU9a9a3NU0xniJBYzxitOnod9tCaT0u5M/G3zGUx2e4tnrn6VaxWrFXTVjTBGxgDGFThXueziOba17Q/ByJnSdwPB2w4u7WsaYImYBYwrdq+8c4JNK3fG96Dem95vBHc3Pm+PUGFMOWMCYQvXFit95altXfIMO8WXUV3RvelNxV8kYU0wsYEyhid62hn5f98CnInxz+zK6NM11LjxjTBlmC4abQrFwxyK6zIggNb4qH3b+kS5XWrgYU95ZwJgC+/iXj+kxoycphy7l2XorueOmpsVdJWNMCWABYwpk4k8TufOzO9E919Dt4HLGPlm3uKtkjCkhvBowItJNRLaJyA4RGZnF/gkissH1+l1E4lzbI9y2bxCRBBHp49rXWER+FpHtIvKJiPi7tld0fd7h2h/szWsr71SVkYtHMmLhCCrt7kfD5d/y8fsX4CwyaowxXgwYEfEF3gK6A82AKBFp5l5GVUeoaqiqhgJvAJ+5tke7be8MnAEWuQ4bB0xQ1RDgGHCfa/t9wDFVbQJMcJUzXpCUksQ9X9zDuB/H0eivf5A8czafzgqgZs3irpkxpiTxZgumDbBDVXeqaiIwC+idQ/koYGYW228FvlHVMyIiOIEz17XvA6CP631v12dc+29wlTeF6EzSGfp+0pcPNn7ADb5j2Pv2ZCa85ku49ekbYzLxZsDUB/a5fY51bTuPiFwMNAaWZrE7knPBUxuIU9XkLM6Z/n2u/cdd5U0hOXLmCDdMv4FvdnzDiJC3iR49mttuE4YOLe6aGWNKIm8+B5NV60GzKRsJzFXVlAwnEKkLNAcWenBOj75PRIYAQwAaNWqUTXVMZnuP76XrR13ZeWwn/+syh3/360eTJjB1KtbvYozJkjdbMLFAQ7fPDYAD2ZR1b6W4uw34XFWTXJ8PAzVEJC0Y3c+Z/n2u/RcARzOfUFWnqGq4qoYHBQXl4XLKr81/b6bDux04cPIA39yxiBnP9iMuzlmVsprNXWmMyYY3A2YNEOIa9eWPEyLzMxcSkcuAmsCqLM6RoV9GVRWIxumXARgEfOF6P9/1Gdf+pa7ypgB+3Psj175/LSmawvLBy1k2rSNLl8LkydCiRXHXzhhTknktYFz9IMNwbm/9BsxW1c0iMlZEbnErGgXMyhwGrmHGDYHvM536aeBxEdmB08fyrmv7u0Bt1/bHgfOGRZu8+XLbl9z44Y0EVQ5i5b0r+XPj1Tz/PAweDPfcU9y1M8aUdFKe/5IfHh6uMTExxV2NEum99e8x5MshhNUNY8EdCzh7LIiwMLjoIvj5Z6hsKxkbU26JyFpVzXXsqD3JbzJQVV784UXum38fnRt3ZundS6nhH8Ttt0NCAsyda+FijPGMzaZs0qVqKiO+HcGk1ZOIuiqKaX2m4e/rz5NPwsqVMHMmXHZZcdfSGFNaWMAYAM4mn2XwF4OZ9esshrcdzmtdX8NHfPjiC3j1VRg6FCIji7uWxpjSxALGcPLsSfrN7sfinYsZd+M4nuzwJCLCzp0waBC0agXjxxd3LY0xpY0FTDn39+m/6TGjBxv+3MD7vd9ncOhgwOlvue02p8zs2VCxYvHV0RhTOlnAlGM7j+2k60dd2X9iP19EfkHPpj3T9/3zn7B2LcybB5dcUoyVNMaUWhYw5dSGPzfQ7aNuJKYksuTuJbRv2D5936xZzoOU//wn9M5pelJjjMmBDVMuh6J3RXP9+9dTwbcCK+5dkSFctm2DBx6ADh3gxReLsZLGmFLPAqacmbtlLt1mdKPhBQ1Zee9KmgWdW6LnzBm49VYICIBPPoEKFYqxosaYUs8Cphx5e83b3DbnNsLrhfPDPT/Q8IKGGfY//DBs3gwzZkCDBsVUSWNMmWEBUw6oKqOjRzN0wVB6Nu3Jd3d9R61KtTKUef99mDYNnn0WbrqpeOppjClbrJO/jEtJTWHo10OZsm4K94Tew5Sbp+Dnk/Ff+6ZNzoOUnTvD6NHFVFFjTJljAVOGJSQncMend/D51s955tpneKHzC2ReRfrECRgwAGrUgI8/Bl/fYqqsMabMsYApo+IS4ug9qzfL9yxnYteJPNbusfPKqMKQIbBjByxdChdeWAwVNcaUWRYwZdCBkwfo9lE3th7eysz+M4m8KutJxCZPdkaLvfgidOxYxJU0xpR5FjBlzLbD2+j6UVeOxB/h6zu+psulXbIst2YNjBgBPXrAU08VcSWNMeWCV0eRiUg3EdkmIjtE5LwVJkVkgohscL1+F5E4t32NRGSRiPwmIltcK1wiIj+4HXNAROa5tncSkeNu+0Z589pKotX7V3PNe9dwJukM0YOisw2XY8ececbq1oXp08HHxhIaY7zAay0YEfEF3gK6ALHAGhGZr6pb0sqo6gi38o8AYW6nmA68oKrfiUhVINV1zHVux3wKfOF2zA+q2ssb11PSLdyxkP6z+1OnSh0WDlxISO2QLMupOjMk798PP/wAtWsXcUWNMeWGN//u2gbYoao7VTURmAXkNLNVFDATQESaAX6q+h2Aqp5S1TPuhUWkGtAZmOeNypcmMzbNoNfMXjSp1YQf7/0x23ABeO01+PJLeOUVaNu2CCtpjCl3vBkw9YF9bp9jXdvOIyIXA42Bpa5NTYE4EflMRNaLyCuuFpG7vsASVT3htq29iGwUkW9E5MrCuYySbfyq8Qz8fCDXNrqW7wd/T91qdbMtu2IFjBwJ/fvDo48WYSWNMeWSNwNGstim2ZSNBOaqaorrsx9wHfAE0Bq4BBic6Zj0Fo/LOuBiVb0aeINsWjYiMkREYkQk5tChQ55cR4mkqjz13VP8c9E/6X9Ff7658xsuCLgg2/KHDsHtt0NwMLz7LkhW/3aMMaYQeTNgYgH3ya4aAAeyKRtJxrCIBda7bq8l44RFy7SdIlIb5xbc12nbVPWEqp5yvV8AVBCRwMxfpKpTVDVcVcODgoLyd2XFLCklicFfDOaVla/wUPhDfHLrJwT4BWRbPiUF7rwTjhyBuXPhguxzyBhjCo03A2YNECIijUXEHydE5mcuJCKXATWBVZmOrSkiaQnQGdjitn8A8JWqJrid5yJxPaYuIm1wru1IIV5PiXA68TR9PunD9I3TGdtpLG/1eAtfn5wfv3/hBfjuO3jjDQgNLaKKGmPKPa+NIlPVZBEZBiwEfIH3VHWziIwFYlQ1LWyigFmqqm7HpojIE8ASV2isBf7ndvpI4KVMX3kr8JCIJAPxQKT7OcuCI2eO0PPjnqw5sIZ3er3DkFZDcj1myRIYMwYGDoT77/d+HY0xJo2Usd/gPAkPD9eYmJjiroZH9h7fS9ePurLr2C5m9p9J3yv65nrMgQMQFgaBgbB6NVSpUgQVNcaUeSKyVlXDcytnT/KXAr/+/SvdPurGqcRTLLprEddffH2uxyQnQ2QknDoF0dEWLsaYomcBU8Kt2LuCm2feTCW/Siy/ZzktLmzh0XHPPus8SPnhh9CsWe7ljTGmsNkkISXY/G3z6fJhF+pUqcPK+1Z6HC5ffQXjxjkzJQ8c6OVKGmNMNjwKGBH5VER6iogFUhF5d9279P2kL83rNGfFPSsIrhHs0XF79sDddzujxV5/3bt1NMaYnHgaGG8DdwDbReQlEbnci3Uq11SV//fD/+P+L+/nxktuZOmgpQRV8ex5ncREZxLLlBSYMwcCsn80xhhjvM6jPhhVXQwsFpELcIYVfyci+3CGDn+kqklerGO5kaqpDP92OG+sfoM7m9/Je73fw9/X3+Pjn3zSGS02dy40aeLFihpThFJTU/n777/Zv3//ea/Y2Fj279/PwYMHERECAgIyvCpVqnTetoLsy2q7j01Hni2PO/ldT88PBO4C1gMzgGuBQUAnb1SuPDmbfJZB8wbxyeZPGNFuBK/e9Co+ebgjOWcOTJoEjz3mzDVmTGkQHx/PgQMHiN23j/1797J/3z72u0Jj/4EDxB44wMFDh0hOTs5wnI+PD3Vr1aJ+rVpcXrMmEQ0b4uPrS0JysvNKSSEhKYn4xEQSTp/meFISCYmJ515nzxJ/9izx8fEU9FGNChUqeCXMPAk6Pz+/85ZBL0k8eg5GRD4DLgc+BKap6kG3fTGejIcuiUrKczAnz56k7yd9WbJrCS/f+DJPdHgiT//RbN8OrVo5o8WWLwd/zxs9pixRhaQk515pVn/mdV8BzqVnz3IkPp79p0+zPz6e2Ph49p89y/7ERPYnJbE/OZn9qakczeL3pwrOvFL1s3k1AC7EeXq7wP/IgGQgAUgQIcHfnwQ/P+L9/Ejw9SUh7U8fn/Q/4318nLIiznFur3hVEtJeqalO0Ln+jE9JOReArldipuDMKx8fn3wHVufOnenevXu+vrewn4N5U1WXZrWjtIZLSfHXqb/o8XEPNv65kWm9pzEodFCejo+PhwEDoEIFmD3bwqVUUIXTp50ZSP/++9zL/fPhw5CQkLcf95SU3L+7IETA359EPz8O+Pmx38fHeamyX5XY1FQnOJKTOZCYyNlM4SFAnYAA6letSuNq1bi2WjXqV69O/Ro1nFft2tSvVYvq1asj/v7Of9TZ/Zl5m58fpKbmORwlMZEKSUlUSEykWgFDlcRE5wG0rPZlEySpwFlc4QTnBVZCbvtSU4k/c4aEM2ecEHQPPxHigWNpZTOFX8Xffst3wHjK04C5QkTWqWocgIjUBKJUdbL3qlb27Ty2k5s+vIkDJw/wReQX9GzaM8/nePRR2LgRvv4aGjXyQiWNZxISzgVETsGR9j4+PuvzVKkCdeo40y9UquS8Lrgg5x9XT/flUkb9/IiLj2f/0aPsP3yY/YcOsf/vv9n/11/sP3jQuWUVG0tWs5AHBARQv3596tevT7v69WnQoEH657RX3bp1qVChgpf/RZRQqalZho9PUhKVEhOplJREzUJsQXq0r2fef2/yytOAeUBV30r7oKrHROQBwAImn9YfXE/3Gd1JSk1i6aCltGvQLs/nmD4dpk6FZ56BHj28UMnyLCnJaUVkFQ5ZfT55Muvz+Ps7gZH2uuKKc++DgjLuCwqCypW9cjnJycn8+eef5zrGd+zIstP8zJkz5x0bGBiYHhLh4eHUzyJAatasWaL7Aoqdj4/z30I5u8XgacD4iIikTR7pWvyrfP2TKkRLdy2lz6w+1AioQfSgaK4IuiLP59i8GR56CDp2hLFjvVDJsiY1FY4ezblV4f7+6NGsz+Prey4YgoKgTZvzw8L9fbVqXl985+TJk9mOrkp7/fXXX6SmpmY4zt/fn3r16lG/fn3CwsLo1atXemCkBUi9evWoWLGiV+tvyi5PA2YhMFtE/g+nX+wfwLdeq1UZNmfzHAZ+PpAmtZqwcOBCGlRvkOdznDoFt94KVavCzJnO7edyRxWOH/e8hXH4sBMymYlA7drnQqF58+zDok4dqFHD+dtoEUhJScl2eK57iJzMovVUo0aN9JBo0aLFeber6tevT2BgoA2xNV7l6U/T08CDwEM4fXWLgKneqlRZ9dbqt3jkm0fo0LAD86PmU6tSrTyfQxUefBB+/91Z46Vu9isklz6nT+fewnD/nJTN41cXXHAuEJo0gQ4dsm9l1K5d7Amtquzdu5f169env3755RdiY2PPG57r6+tL3bp1qV+/PldeeSU33XRTluFR2Uu32ozJC08ftEzFeZr/be9Wp2xSVUZFj+L5H57n5qY3M+vWWVSukL8fgClT4OOP4b//hc6dC7mi3qIKP/4IO3fmHBw5dXynBUKDBtCyZfatjMBAKMG3dJKTk9m2bVuGMNmwYQPHjh0DnGGnl112Ge3btyc4OPi8vo46derg61sYA3SN8T6PAkZEQoAXgWZA+gQkqnqJl+pVZiSnJjP066H8b93/uDf0Xt65+R38fPL3N+Z165xRY127wr/+VcgV9aZJk2D48HOf3Tu+g4Lg8suzDougIOdVStcaOHPmDL/88kuGINm0aRMJCc5CrAEBATRv3pwBAwYQFhZGaGgoLVq0sNaHKTM8/aV7HxgNTAAigHtwbpXlSES6Aa/jPBM1VVVfyrQ/7XwAlYE6qlrDta8Rzm24hjj9Pj1UdbeITAM6Asddxw1W1Q2ulS9fB3oAZ1zb13l4fV4RnxTPHZ/dwbyt8/jXtf/i+c7P53ukTVyc87xLUJAzBX+puXW+aRM89ZQzJHLixCLr+C5qR48ezRAk69evZ+vWrekd6zVq1CAsLIyhQ4cSGhpKWFgYl19+OX7lsgPNlBee/tddSVWXuEaS7QHGiMgPOKGTJddIs7eALkAssEZE5qvqlrQyqjrCrfwjQJjbKaYDL6jqdyJSFeeZpDRPqurcTF/ZHQhxvdri3M5r6+H1Fbq4hDhumXkLK/YE2cFlAAAgAElEQVSuYFK3STzS9pF8n0sV7r0X9u6F7793QqZUiI+HqCioVQvef78UVTx7qsq+ffsyBMn69evZu3dvepkGDRoQFhZG//79CQsLIywsjIsvvtiG8Zpyx9OASXBN1b9dRIYB+4E6uRzTBtihqjsBRGQW0BvYkk35KFyBJSLNAD9V/Q5AVU95UMfewHTXUOqfRKSGiNR1n9amqBw4eYCuH3Vl2+FtzOw/k9uvur1A55s4ET7/HF591emvLjWefBK2bIGFC0tluKSkpKT3l7iHyVHXEGYR4bLLLqNDhw48/PDD6be5gkrhtRrjDZ4GzHCcW1iPAv/Fua2V25wm9YF9bp9jyaZFISIXA42BtOlomgJxrjnQGgOLgZGqmjYXxgsiMgpY4tp+Npvvqw8UacBsO7yNrh915Uj8ERbcuYAbL7mxQOdbtcq5w9S7Nzz+eCFVsih89RW89RaMGAE33VTctclVfHw8v/zyS4Yg2bRpE/GugQf+/v40b96cfv36pbdKWrRoQZVS2j9kTFHINWBct7puU9UngVM4/S+eyOp+QHYza0YCc90CxA+4DueW2V7gE2Aw8C7wDPAnzoOeU3CGUI/19PtEZAgwBKBRIc+tsnr/anrM6IGvjy/LBi2jVb1WBTrf4cPO+i4NG8K0aaWo2+LPP+Gee+Dqq+HFF4u7Nuc5duxYhiBJ6y9Jcc3ldcEFFxAaGsqDDz6YHiaXX355+Z3mxJh8yjVgVDVFRFq5P8nvoVicDvo0DYAD2ZSNBB7OdOx6t9tr84B2wLtut7zOisj7wBN5+T5VnYITTISHhxdsnm433+74lv6z+3NR1YtYOHAhTWoVbEGW1FRnZcq//4aVK53n+0qF1FQYPNh5GvTjj4t1yLCqsn///gxBsn79evbs2ZNepl69eoSFhdG3b9/0MAkODrb+EmMKgae3yNYDX4jIHOB02kZV/SyHY9YAISLSGKfPJhJnVcwMROQyoCawKtOxNUUkSFUPAZ2BGFf5uqp60DVqrA/wq+uY+cAwV19PW+B4UfW/fLTpI+754h6uqnMV39z5DRdVvajA53zpJfjmG5g82ZmKv9SYNMnpc5k82Vk/oIikpKSwffv2854vOXz4MOD0l4SEhNCuXTseeuih9P6SOnVy60o0xuSXpwFTCziC80OfRoFsA0ZVk10DAhbiDFN+T1U3i8hYIEZV57uKRgGz3FtHrlbTE8ASV5CsxVk9E2CGiATh3BLbgDNtDcACnCHKO3CGKXt6K69AXlv5Gk989wQRwRHMi5xH9YrVC3zO6Gh47jmIjIR//CP38iXGxo3w9NNwyy1erXhCQgK//vprhjDZtGlT+kSN/v7+XHXVVfTu3Tt9SPDVV19N1apVvVYnY8z5PFpwrKwqyIJjqZrK0989zaurXuXWZrfyUd+PqOhX8NtBf/4JoaHOLbE1a5xHRkqF+HgID3cmidy0qdBGjcXFxWXoL9mwYQNbtmxJ7y+pXr06oaGh6UESFhbGFVdcgX85m7XWmKJUqAuOufo6zksiVb03H3Ur9ZJSkrhv/n18uOlDhoYPZVL3Sfj6FHz6jpQU57GREydg8eJSFC4ATzzhDEletChf4aKqHDhw4LyHFXft2pVepm7duoSGhnLzzTenh0njxo1twkZjSihPb5F95fY+AOhL9h32Zd60DdP4cNOHjO00lmevf7bQOoRHj4Zly5wRY1ddVSinLBpffun0uTz+OHTpkmvx1NTUDP0laWHivpBVkyZNCA8P54EHHkgPkwsvvNCbV2GMKWT5ukXmeuhysaqWlukWs5TfW2Spmkr0rmhuuOSGQqvLN984i4bdey+8+26hndb7Dh6EFi2cSSh/+inLUWOJiYnMnDmTNWvWsH79ejZu3Mjp085YkQoVKnDllVemh0haf0m1UtV8M6Z8KdRbZFkIAcrtAr0+4lOo4bJvH9x1l7MUyRtvFNppvS9tSPLp09kOSd69eze33347q1evpmrVqoSGhnLvvfemh0mzZs2sv8SYMsrTPpiTZOyD+RPnAUdTQImJzsOUZ8/C3LleWzHXO15/3elzefttZyngTObPn8+gQYNITU1l9uzZ9O/f3/pLjClHPF0Pxu5XeMkzzzh3lj75BJo2Le7a5MGGDTBypDOHzYMPZtiVlJTEyJEjGT9+PC1btmT27NlceumlxVRRY0xx8eivkyLSV0QucPtcQ0T6eK9a5cPnn8P48TBsmNOKKTXOnIE77nBWg5w6NcMcNnv37uX6669n/PjxPPzww6xcudLCxZhyytP7FaNVNW39FVQ1jhym6je5++MPZ7qu8HBnluRS5Ykn4LffYPp0ZwVJl6+++orQ0FA2b97M7NmzefPNN6lYgleXNMZ4l6cBk1U5WykpnxISnMXDRGD27BK9wu/55s93+lyeeAJudGaKTkpK4qmnnuLmm2/m4osvZt26dQwYMKCYK2qMKW6ehkSMiIzHWUBMgUdwpm8x+TBiBKxfD198AY0bF3dt8uDgQbjvPggLgxdeAGDfvn1ERkaycuVKHnroIcaPH09AQEAuJzLGlAeetmAeARJxps2fDcSTcfZj46GPP4b/+z9nLa5bbinu2uRBaioMGnRuSLK/PwsWLCAsLIxNmzYxc+ZMJk+ebOFijEnn6Siy08BIL9elzPvtNxgyBK69Nr0BUHpMnAjffQfvvENykyY8O3Ik48aN4+qrr2b27Nk0LVVD4IwxRcHTUWTfiUgNt881RWSh96pV9pw+7fS7VKoEs2ZBqVq7av16Z0hy377Edu9OREQE48aNY8iQIaxatcrCxRiTJU/7YAJdI8cAUNVjImILaXhIFYYOPbc8ff36xV2jPEgbkhwUxLeRkdzVsiXx8fHMmDGDO+44b3kfY4xJ52kfTKqIpE8NIyLBZL/8scnkvfecEb2jRnk0F2TJ8vjjJG/dyr87daL77bdTt25d1q5da+FijMmVpy2YfwMrROR71+frca1rb3K2caPzIOWNNzqLiJUq8+Zx4J13iGrQgOUff8x9993HpEmTqFyq5rMxxhQXj1owqvotEA5swxlJ9k+ckWQ5EpFuIrJNRHaIyHmDBERkgohscL1+F5E4t32NRGSRiPwmIltcrSZEZIbrnL+KyHsiUsG1vZOIHHc73yhPrs2bTpyAW2+FmjVhxgzwLfiSMUXnwAEW3X03oX5+xBw9yvTp05k6daqFizHGY55Odnk/8BjQAGeZ4nbAKjIuoZz5GF+c52a6ALHAGhGZr6pb0sqo6gi38o8AYW6nmA68oKrfiUhVINW1fQYw0PX+Y+B+4G3X5x9UtZcn1+RtqnD//bBrFyxdCqVp6feUpCTGXHMNL5w8SbOQEOZ88QVXZDGZpTHG5MTTPpjHgNbAHlWNwAmCQzkfQhtgh6ruVNVEYBbQO4fyUcBMABFpBvip6ncAqnpKVc+43i9QF2A1TuiVOG++CXPmOMORr7++uGvjuYMHD3LjFVfw/O7dDO7QgdUbNli4GGPyxdOASVDVBAARqaiqW4HLcjmmPrDP7XOsa9t5RORioDGw1LWpKRAnIp+JyHoRecXVInI/pgJwF/Ct2+b2IrJRRL4RkSs9vLZCt3o1/POf0KuX80BlabFkyRJCr7qKn//4g2ktW/LeihV2S8wYk2+eBkys6zmYecB3IvIFuS+ZnNU6wtmNPIsE5qpqiuuzH3Ad8AROy+kSYHCmYyYDy1X1B9fndcDFqno18IarrudXSmSIiMSISIz7Er2F5ehRZ2bkevXggw+gNCx/kpKSwpgxY+jSpQuBp06xpk4dBi1alGGWZGOMyStPO/n7qmqcqo4BngPeBXKbrj8WaOj2uQHZh1Ikrttjbseud91eS8YJi5ZpO0VkNBAEPO5WxxOqesr1fgFQQUQCyURVp6hquKqGBwUF5XIJeZM2m8qBA84klrVqFerpveLPP//kpptu4j//+Q93NWnC6sRErpw505mK3xhjCiDPf79W1e9Vdb6rXyUna4AQEWksIv44ITI/cyERuQyoiTNowP3YmiKSlgCdgS2u8vcDXYEoVU11O89FIs5fuUWkjevajuT1+gri1Vfhq6/gtdegTZui/Ob8Wbp0KaGhoaxatYr3Hn6YD7Zvp8pTT0HnbMduGGOMx7x2A8fV8hgGLAR+A2ar6mYRGSsi7tM8RgGzXJ32acem4NweWyIiv+Dcbvufa/f/ARcCqzINR74V+FVENgKTgEj3c3rb8uXwr38508EMG1ZU35o/KSkpjB07li5dulCzZk1Wf/kl98ycCa1awX//W9zVM8aUEVKEv8ElTnh4uMbExBT4PH//DaGhUKUKrF0L1asXQuW85K+//mLgwIEsXryYgQMH8vZbb1G1Xz9YtQrWrYPLchu7YYwp70RkraqG51bOFg0roJQUZ6quY8fgm29KdrgsW7aMqKgo4uLimDp1Kvfeey/y6quwZAn8738WLsaYQlUKxjiVbP/9r/P7/OabcPXVxV2brKWmpvL8889zww03UL16dX7++Wfuu+8+ZP16+Pe/oV8/ZyExY4wpRNaCKYDvvoOxY+Huu+Hee4u7Nlk7dOgQAwcOZNGiRURFRfHOO+9QrVo1Z/2AqChnioH//c+GJBtjCp0FTD7t3w933gnNmsHkySXz93n58uVERUVx5MgR3nnnHR544AEkraIjRsD27U7zqzSMpzbGlDp2iywfkpIgMtJZKmXOHKdzvyRJTU3lxRdfJCIigipVqvDzzz8zZMiQc+Hy+edOq+WppyAiongra4wps6wFkw/TpsGKFc4MySVtmq7Dhw9z11138e2333L77bczZcoUqruPPNi/35mFs1Ur5/6eMcZ4iQVMPtx7rzMVTM+exV2TjH788Uduv/12Dh06xOTJk/nHP/5xrtUCzlQDd98NCQnw8cfg7198lTXGlHl2iywffH1LVrikpqby8ssv07FjRwICAvjpp5946KGHMoYLOFMNLF0KkyZB06bFU1ljTLlhLZhS7siRI9x9990sWLCAAQMGMHXq1Iy3xNKsXesMSe7fv+QOeTPGlCkWMKXYypUruf322/n777958803GTp06PmtFnCGJN9xB1x0EUyZUjKHvBljyhwLmFJIVXnttdd45plnaNiwIStXrqRVq1bZHzB8uDMkeelSG5JsjEtSUhKxsbEkJCQUd1VKrICAABo0aECFChXydbwFTClz9OhRBg8ezJdffkm/fv149913qVGjRvYHfPopTJ0KI0dCp05FVk9jSrrY2FiqVatGcHBw1i3/ck5VOXLkCLGxsTRu3Dhf57BO/lLkp59+IiwsjG+//ZZJkyYxd+7cnMMlNhYeeADCw+E//ym6ihpTCiQkJFC7dm0Ll2yICLVr1y5QC88CphRQVcaPH891112Hj48PP/74I4888kjO/2OkpDhDkhMTbUiyMdmwcMlZQf/52C2yEu7YsWPcc889fPHFF/Tp04f33nuPmjVr5n7gq69CdDS8+y6EhHi/osYYk4m1YEqw1atXExYWxtdff82ECRP47LPPPAuXmBh49lm49Va45x7vV9QYky9Vq1ZNf9+tWzdq1KhBr169cj1u4sSJnDlzJs/fN2rUKBYvXpzn4/LLqwEjIt1EZJuI7BCRkVnsn+BalXKDiPwuInFu+xqJyCIR+U1EtohIsGt7YxH5WUS2i8gnruWYEZGKrs87XPuDvXlt3qSqvP7661x77bUArFixguHDh3vWXD11yoYkG1MKPfnkk3z44Ycelc0pYFJSUrI9buzYsdx44435ql9+eC1gRMQXeAvoDjQDokSkmXsZVR2hqqGqGgq8AXzmtns68IqqXgG0Af52bR8HTFDVEOAYkLaQyX3AMVVtAkxwlSt14uLi6N+/P8OHD6d79+6sW7eOtm3ben6C4cNhxw746CPwpLVjjCkRbrjhBmcpjVxMmjSJAwcOEBERQYRrstqqVasyatQo2rZty6pVqxg7diytW7fmqquuYsiQIaStXDx48GDmzp0LQHBwMKNHj6Zly5Y0b96crVu3Fvo1ebMPpg2wQ1V3AojILKA3sCWb8lHAaFfZZoCfqn4HoKqnXNsF6Azc4TrmA2AM8Lbr3GNc2+cCb4qIaClaEzomJobbbruNffv28dprrzFixIi8dbJ9+qnT5/LMM9Cxo/cqakwZM3w4bNhQuOcMDYWJEwv3nACPPvoo48ePJzo6msDAQABOnz7NVVddxVjXBLbNmjVj1KhRANx111189dVX3HzzzeedKzAwkHXr1jF58mReffVVpk6dWqh19eYtsvrAPrfPsa5t5xGRi4HGwFLXpqZAnIh8JiLrReQVV4uoNhCnqslZnDP9+1z7j7vKl3iqyhtvvEGHDh1ITk5m+fLlPP7443kLl337nCHJrVvbkGRjyhlfX1/69++f/jk6Opq2bdvSvHlzli5dyubNm7M8rl+/fgC0atWK3bt3F3q9vNmCyerXMbvWRCQwV1XTbh76AdcBYcBe4BNgMDA/h3N69H0iMgQYAtCoUaNsqlN0jh8/zn333cenn35Kz549+eCDD6hdO4+5mHlIcj6fujWmvPJGS6MoBQQE4OvrCzjP9wwdOpSYmBgaNmzImDFjsn2WpWLFioATUMnJyVmWKQhvtmBigYZunxsAB7IpGwnMzHTselXd6WqNzANaAoeBGiKSFozu50z/Ptf+C4Cjmb9IVaeoariqhgcFBeXrwgrLunXraNmyJfPmzePll19m/vz5eQ8XgFdegWXL4I03oEmTQq+nMaZkqVatGidPnsxyX1qYBAYGcurUqfQ+l+LgzYBZA4S4Rn3544TIeS0QEbkMqAmsynRsTRFJS4DOwBZXf0o0cKtr+yDgC9f7+a7PuPYvLan9L6rK5MmTad++PYmJiSxfvpwnn3wSH598/OtYswaeew4GDIDBgwu9rsaYonHdddcxYMAAlixZQoMGDVi4cGG2ZYcMGUL37t3TO/nd1ahRgwceeIDmzZvTp08fWrdu7c1q50xVvfYCegC/A38A/3ZtGwvc4lZmDPBSFsd2ATYBvwDTAH/X9kuA1cAOYA5Q0bU9wPV5h2v/JbnVr1WrVlrUjh8/rrfddpsC2r17dz106FD+T3bypGpIiGrDhqpHjxZeJY0pB7Zs2VLcVSgVsvrnBMSoBxng1Sf5VXUBsCDTtlGZPo/J5tjvgBZZbN+JM0It8/YEYEABqut169ev57bbbmPXrl289NJL+W+1pHnsMWdIcnS0DUk2xpQ4NlVMEVBV3nnnHYYPH05gYCDLli1Lf4gy3+bOhffeg3/9y4YkG1NG9e3bl127dmXYNm7cOLp27VpMNcobCxgvO3nyJEOGDGHWrFl07dqVDz/8kAIPLkgbktymDYwZUyj1NMaUPJ9//nlxV6FAbC4yL9q4cSOtWrVi9uzZvPDCCyxYsKDg4ZKSAnfdBcnJMGOGDUk2xpRY1oLxAlVl6tSpPProo9SsWZPo6Giuv/76wjn5yy/D99/D++/bkGRjTIlmLZhCdurUKQYOHMiQIUO47rrr2LBhQ+GFy5o1MGoU3HYbDBqUe3ljjClGFjCF6JdffiE8PJxZs2bx3//+l2+//ZY6deoUzsnTZkmuWxf+7/9slmRjTIlnAVMIVJV3332XNm3acPz4cRYvXsyzzz5bsCHImT36KOzcabMkG1OGFPV6MADz5s1jy5bs5hwuXBYwBXTq1CkGDRrE/fffzzXXXMOGDRuyfLq2QObMcfpcnnkGCut2mzGmRCms9WByYwFTSvz666+0bt2ajz76iP/85z8sXLiQCy+8sHC/ZO9eGDIE2raF0aML99zGmBKjIOvBLFq0iPbt29OyZUsGDBjAqVOnABg5ciTNmjWjRYsWPPHEE6xcuZL58+fz5JNPEhoayh9//OHVa7JRZPk0bdo0hg4dSvXq1Vm8eDGdO3cu/C+xIcnGFI1StCBM5vVgDh8+zPPPP8/ixYupUqUK48aNY/z48QwbNozPP/+crVu3IiLExcVRo0YNbrnlFnr16sWtt96a+5cVkAVMPrz33nvcd999RERE8PHHH3PRRRd554vGjYPly2HaNLj0Uu98hzGmVPvpp5/YsmUL11xzDQCJiYm0b9+e6tWrExAQwP3330/Pnj096tspbBYw+RAZGcnJkycZNmxY+hoMhW71aueW2O23O2u9GGO8pxQvCKOqdOnShZkzZ563b/Xq1SxZsoRZs2bx5ptvsnTp0izO4D3WB5MPlStX5rHHHvNeuJw86QxJrlfPhiQbY87jvh5Mu3bt+PHHH9mxYwcAZ86c4ffff+fUqVMcP36cHj16MHHiRDa4bgHmtJZMYbOAKYkefRR27XKGJNeoUdy1McYUgfyuBxMUFMS0adOIioqiRYsWtGvXjq1bt3Ly5El69epFixYt6NixIxMmTACcOzCvvPIKYWFhXu/kFy2Za3IVifDwcI2JiSnuamQ0e7ZzW+zZZ+G//y3u2hhTZv32229cccUVxV2NEi+rf04islZVw3M71lowJYn7kORRo3Ivb4wxJZhXO/lFpBvwOuALTFXVlzLtnwCkPZVYGaijqjVc+1JwVrME2Kuqt7i2/wCkDRavA6xW1T4i0gln+eS0xRM+U9WxXrkwb0hJgYEDnT9tSLIxBlsPJlsi4gu8hbP0cSywRkTmq2r6I6SqOsKt/CNAmNsp4lU1NPN5VfU6t2M+xQmVND+oatGPxSsML70EP/wAH3xgQ5KNMYCtB5OTNsAOVd2pqonALKB3DuWjgPPH2WVDRKoBnYF5BaplSfDzz86Q5MhI58FKY4wpA7wZMPWBfW6fY13bziMiFwONAfdB2gEiEiMiP4lInywO6wssUdUTbtvai8hGEflGRK4sYP2LRtqQ5AYN4O23bUiyMabM8GYfTFa/lNkNWYsE5qpqitu2Rqp6QEQuAZaKyC+q6j6mLgqY6vZ5HXCxqp4SkR44LZuQ8yolMgQYAtCoUSPPr8ZbHnkEdu92FhGzIcnGmDLEmy2YWKCh2+cGwIFsykaS6faYqh5w/bkTWIZb/4yI1Ma5Bfe1W/kTqnrK9X4BUEFEAjN/kapOUdVwVQ0v8PLFBfXJJ06fy7//DddeW7x1McaYQubNgFkDhIhIYxHxxwmR+ZkLichlQE1gldu2miJS0fU+ELgGcJ9fegDwlaomuB1zkYhzf0lE2uBc25FCv6rCsmcPPPggtGtnQ5KNKafS1oPZsGED7du358orr6RFixZ88sknOR6X3+n6R40axeLFi/NV1/zw2i0yVU0WkWHAQpxhyu+p6mYRGQvEqGpa2EQBszTjE59XAO+ISCpOULzkPvoMJ6wyDHkGbgUeEpFkIB6IzHTOkiNtluTUVGdIsp9NCWdMeVa5cmWmT59OSEgIBw4coFWrVnTt2pUa2dw2nzhxIgMHDqRy5crn7UtJScl2GquxY4v2yQ2v/rK5blUtyLRtVKbPY7I4biXQPIfzdspi25vAm/msatF68UVnSPL06XDJJcVdG2PKveHfDmfDn4U7XX/oRaFM7ObZJJpNmzZNf1+vXj3q1KnDoUOHsgwY9/VgAgMDiY6OpmrVqjz++OMsXLiQ1157jaVLl/Lll18SHx9Phw4deOeddxARBg8enD5Vf3BwMIMGDeLLL78kKSmJOXPmcPnllxfa9YM9yV/0fvoJxoyBqCjnwUpjjHGzevVqEhMTuTSb5+EeffRR6tWrR3R0NNHR0QCcPn2aq666ip9//plrr72WYcOGsWbNGn799Vfi4+P56quvsjxXYGAg69at46GHHuLVV18t9GuxezNF6cQJuPNOG5JsTAnjaUvD2w4ePMhdd93FBx98gI+P53//9/X1pX///umfo6Ojefnllzlz5gxHjx7lyiuv5Oabbz7vuH79+gHQqlUrPvvss4JfQCYWMEUpbUjy8uVwwQXFXRtjTAly4sQJevbsyfPPP0+7du3ydGxAQEB6v0tCQgJDhw4lJiaGhg0bMmbMGBISErI8rmLFioATUMnJyQW7gCzYLbKiMmuW0+fy7LPgWnnOGGPAWYWyb9++3H333QwYMCDX8jmt6ZIWJoGBgZw6dYq5c+cWal3zwlowRWHPHvjHP6B9e3juueKujTGmhJk9ezbLly/nyJEjTJs2DYBp06YRGnredIzAufVg6tatm94Pk6ZGjRo88MADNG/enODgYFq3bu3t6mfL1oPx9nowyckQEQEbNzqvxo29+33GGI/YejCeKch6MNaC8bYXX4QVK+DDDy1cjDHligWMN61aBf/5jzOZpQ1JNsbkka0HY7KWNiS5YUOYPLm4a2OMKYVK+3owFjDeMmyY07lvQ5KNMeWUDVP2hpkznT6X556zIcnGmHLLAqaw7d7tDEnu0MF55sUYY8opC5jClJx8rjP/o49slmRjTLlmAVOY/t//gx9/dDr1bUiyMSYXRb0eDMC8efPYsmVL7gULgQVMYVm1CsaOdUaO3XlncdfGGFOKpK0Hs3nzZr799luGDx9OXFxctuVLS8DYPZzC4D4k+a23irs2xpg8Gj58OBs2FPJ6MKGhTJxYNOvBLFq0iNGjR3P27FkuvfRS3n//fapWrcrIkSOZP38+fn5+3HTTTfTr14/58+fz/fff8/zzz/Ppp59muyxAYfBqwIhIN+B1nBUtp6rqS5n2TwAiXB8rA3VUtYZrXwrwi2vfXlW9xbV9GtAROO7aN1hVN7iWS34d6AGccW1f561ry+Dhh2HvXhuSbIwpME/Wgxk/fjzR0dEEBgZy+PBhnn/+eRYvXkyVKlUYN24c48ePZ9iwYXz++eds3boVESEuLo4aNWpwyy23pC865m1eCxgR8QXeAroAscAaEZnvvvSxqo5wK/8IEOZ2inhVzXqmN3hSVTNPEdodCHG92gJvu/70ro8/djr0x4xxRo4ZY0odT1sa3paf9WB++ukntmzZwjWuRyISExNp37491atXJyAggPvvv7Gia9cAAAnMSURBVJ+ePXvSq1cvb1Y9S95swbQBdqjqTgARmQX0BrK7+RcFjC7A9/UGpqsze+dPIlJDROqq6sECnDNnu3bBQw85z7r8+99e+xpjTNmX3/VgVJUuXbowc+bM8/atXr2aJUuWMGvWLN58802WLl1amFXOlTc7+esD+9w+x7q2nUdELgYaA+5XHyAiMSLyk4j0yXTICyKySUQmiEjFvH5fobAhycaYQlKQ9WDatWvHjz/+yI4dOwA4c+YMv//+O6dOneL48eP06NGDiRMnpvcx5bSWTGHzZsBktR5wdmsDRAJzVTXFbVsj13TQdwATRSTthuQzwOVAa6AW8HRevk9EhriCK+bQoUMeXEY2XngBVq50lj4ODs7/eYwx5V7aejBpa8CEhobmOOggbT2YiIgIgoKCmDZtGlFRUbRo0YJ27dqxdetWTp48Sa9evWjRogUdO3ZkwoQJAERGRvLKK68QFhbGH3/84dXr8tp6MCLSHhijql1dn58BUNUXsyi7HnhYVVdmc65pwFeZ+11EpBPwhKr2EpF3gGWqOtO1bxvQKadbZPleD2blSrjuOmeW5A8/zPvxxphiZ+vBeKYg68F4swWzBggRkcYi4o/TSpmfuZCIXAbUBFa5bauZdutLRAKBa3D13YhIXdefAvQBfnUdNh+4WxztgONe638JCIAuXWxIsjHG5MBrHQeqmiwiw4CFOMOU31PVzSIyFohR1bSwiYL/3979xshV1WEc/z7UbcekRKBbobIoVBr/VAUbhEobg8oL0hc0KqYmJoKBF40x0VemRoNBXyia+MKosYokmBAgFKgIBYO00PiiLQ227Na1sm2iblrausZqEwRsf744Z82w3dm5++fcO7DPJ5ns3Zlz7zz37Nw9c8/cOYf74/WnUu8DNks6Q2oEv9d29dm9kpaSusT2ARvz/dtIlyiPkC5T/mKpfWPVKnjyyWKbNzODN/58MJ4yufSUyWbWk9xFVk2vdpGZmfW0+fwGu4rZ1o8bGDObl1qtFmNjY25kOogIxsbGaLVaM96Gv7xhZvPSwMAAo6OjzOrrCm9yrVaLgYGBGa/vBsbM5qW+vj4u87QaRbmLzMzMinADY2ZmRbiBMTOzIub192AknQD+MsPV+4G/z2GcudKruaB3sznX9DjX9LwZc70rIpZ2KzSvG5jZkLS3yheN6taruaB3sznX9DjX9MznXO4iMzOzItzAmJlZEW5gZu7nTQfooFdzQe9mc67pca7pmbe5/BmMmZkV4TMYMzMrwg1MRZI+K+mApDOSOl55IekGSQcljUjaVEOuCyQ9JenF/PP8DuVOS9qXb2dN/DaHeabcf0mLJD2QH98t6dJSWaaZ6xZJJ9rq6Laact0t6bikoQ6PS9KPcu4XJK3qkVzXSTrZVl+315TrEkk7JA3n4/Erk5Sptc4qZmqqvlqS9kjan7PdMUmZcsdkRPhW4UaaBO09wDPAVR3KLAAOAcuBhcB+4P2Fc30f2JSXNwF3dih3qoY66rr/wJeAn+XlzwEP9EiuW4AfN/C6+hiwChjq8Pg64AnSBHurgd09kus60jTmddfXMmBVXj4X+PMkf8ta66xipqbqS8DivNwH7AZWTyhT7Jj0GUxFETEcEQe7FLsaGImIwxHxKnA/sL5wtPXAPXn5HtI00k2psv/tebcAn8zTXzedqxERsRP4xxRF1gO/imQXcN74tOEN52pERByNiOfz8r+BYeDiCcVqrbOKmRqR6+BU/rUv3yZ+8F7smHQDM7cuBv7W9vso5V9oF0bEUUgvdODtHcq1JO2VtEtSqUaoyv7/v0xE/Bc4CSwplGc6uQA+k7tUtki6pHCmqpp4TVX10dz18oSklXU/ee7K+TDpXXm7xupsikzQUH1JWiBpH3AceCoiOtbXXB+THq6/jaTfARdN8tA3IuLXVTYxyX2zvkxvqlzT2Mw7I+KIpOXAdkmDEXFottkmqLL/ReqoiyrP+Rvgvoh4RdJG0ju6TxTOVUUT9VXF86ThQk5JWgdsBVbU9eSSFgMPAV+NiH9NfHiSVYrXWZdMjdVXRJwGrpR0HvCIpA9ERPtna8Xqyw1Mm4i4fpabGAXa3/kOAEdmuc0pc0k6JmlZRBzN3QDHO2zjSP55WNIzpHdZc93AVNn/8TKjkt4CvI3yXTFdc0XEWNuvvwDuLJypqiKvqdlq/wcaEdsk/VRSf0QUH3NLUh/pH/m9EfHwJEVqr7NumZqsr7bn/Wc+9m8A2huYYseku8jm1nPACkmXSVpI+sCs2BVb2aPAzXn5ZuCsMy1J50talJf7gTXAHwtkqbL/7XlvArZH/nSxoK65JvTR30jqR+8FjwJfyFdGrQZOjneJNknSReP99JKuJv0vGZt6rTl5XgG/BIYj4ocditVaZ1UyNVhfS/OZC5LeClwP/GlCsXLHZN1XNbxRb8CnSC39K8Ax4Lf5/ncA29rKrSNdRXKI1LVWOtcS4Gngxfzzgnz/VcBdeflaYJB09dQgcGvBPGftP/Bt4Ma83AIeBEaAPcDymv5+3XJ9FziQ62gH8N6act0HHAVey6+vW4GNwMb8uICf5NyDdLiCsYFcX26rr13AtTXlWkvqvnkB2Jdv65qss4qZmqqvDwF/yNmGgNvz/bUck/4mv5mZFeEuMjMzK8INjJmZFeEGxszMinADY2ZmRbiBMTOzItzAmBUm6VT3UlOuvyWPwICkxZI2SzqUR8fdKekaSQvzsr88bT3DDYxZD8tjVi2IiMP5rrtI37JeERErSaNA90caxPNpYEMjQc0m4QbGrCb5m+U/kDQkaVDShnz/OXnokAOSHpO0TdJNebXPk0dnkPRu4BrgmxFxBtLQPxHxeC67NZc36wk+nTarz6eBK4ErgH7gOUk7SUP3XAp8kDQa9jBwd15nDelb9QArgX2RBi+czBDwkSLJzWbAZzBm9VlLGrH5dEQcA54lNQhrgQcj4kxEvEQaqmbcMuBElY3nhudVSefOcW6zGXEDY1afTpM4TTW508uksaIgjWV1haSpjttFwH9mkM1szrmBMavPTmBDngBqKWla4j3A70mTnZ0j6ULS9LrjhoHLASLN37MXuKNtZN4Vktbn5SXAiYh4ra4dMpuKGxiz+jxCGtV2P7Ad+FruEnuINGLxELCZNBviybzO47y+wbmNNPnciKRB0tw143OdfBzYVnYXzKrzaMpmPUDS4kizHS4hndWsiYiX8hweO/LvnT7cH9/Gw8DXI+JgDZHNuvJVZGa94bE8MdRC4Dv5zIaIeFnSt0jzpv+108p5IrWtblysl/gMxszMivBnMGZmVoQbGDMzK8INjJmZFeEGxszMinADY2ZmRbiBMTOzIv4HUOnIsekJYOMAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "x_axis = np.log10(C_s)\n",
    "plt.plot(x_axis,np.array(accuracy_l1_train), 'b-',label='l1_train')\n",
    "plt.plot(x_axis,np.array(accuracy_l1_test), 'r-',label='l1_test')\n",
    "plt.plot(x_axis,np.array(accuracy_l2_train), 'g-',label='l2_train')\n",
    "plt.plot(x_axis,np.array(accuracy_l2_test), 'k-',label='l2_test')\n",
    "plt.legend()\n",
    "plt.xlabel( 'log(C)' )                                                                                                      \n",
    "plt.ylabel( 'accuracy' )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best_C_l1=100.0,Best_C_l2=100.0\n"
     ]
    }
   ],
   "source": [
    "#最佳超参数\n",
    "index_l1 = np.argmax(accuracy_l1_test,axis=None)\n",
    "index_l2 = np.argmax(accuracy_l2_test,axis=None)\n",
    "Best_C_l1 = C_s[index_l1]\n",
    "Best_C_l2 = C_s[index_l2]\n",
    "print('Best_C_l1={},Best_C_l2={}'.format(Best_C_l1,Best_C_l2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "利用gridsearchcv进行超参数调优"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "GridSearchCV(cv=5, error_score='raise-deprecating',\n",
       "       estimator=LinearSVC(C=1.0, class_weight=None, dual=False, fit_intercept=True,\n",
       "     intercept_scaling=1, loss='squared_hinge', max_iter=1000,\n",
       "     multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,\n",
       "     verbose=0),\n",
       "       fit_params=None, iid='warn', n_jobs=4,\n",
       "       param_grid={'penalty': ['l1', 'l2'], 'C': array([1.e-01, 1.e+00, 1.e+01, 1.e+02, 1.e+03])},\n",
       "       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',\n",
       "       scoring='accuracy', verbose=0)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.model_selection import  GridSearchCV\n",
    "C_s = np.logspace(-1, 3, 5)# logspace(a,b,N)把10的a次方到10的b次方区间分成N份  \n",
    "penalty_s = ['l1','l2']\n",
    "tuned_parameters = dict(penalty = penalty_s, C = C_s)\n",
    "SVC3=LinearSVC(dual=False)\n",
    "grid= GridSearchCV(SVC3, tuned_parameters,cv=5, scoring='accuracy',n_jobs = 4)\n",
    "grid.fit(X_train,y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7695788487022851\n",
      "LinearSVC(C=1000.0, class_weight=None, dual=False, fit_intercept=True,\n",
      "     intercept_scaling=1, loss='squared_hinge', max_iter=1000,\n",
      "     multi_class='ovr', penalty='l1', random_state=None, tol=0.0001,\n",
      "     verbose=0)\n",
      "{'C': 1000.0, 'penalty': 'l1'}\n"
     ]
    }
   ],
   "source": [
    "print(grid.best_score_)\n",
    "print(grid.best_estimator_)\n",
    "print(grid.best_params_)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RBF核SVM正则参数调优"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "#RBF核是SVM最常用的核函数。 \n",
    "#RBF核SVM 的需要调整正则超参数包括C（正则系数，一般在log域（取log后的值）均匀设置候选参数）和核函数的宽度gamma \n",
    "#C越小，决策边界越平滑； \n",
    "#gamma越小，决策边界越平滑。\n",
    "from sklearn.svm import SVC"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fit_grid_point_RBF(C,gamma,X_train,y_train,X_test,y_test):\n",
    "    SVC4 = SVC(C = C,kernel='rbf',gamma=gamma)\n",
    "    SVC4.fit(X_train,y_train)\n",
    "    #返回校验集上的正确率\n",
    "    accuracy = SVC4.score(X_test,y_test)\n",
    "    print('C= {} and gamma= {}:accuracy={}'.format(C,gamma,accuracy))\n",
    "    return accuracy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0.]\n",
      " [0. 0. 0.]\n",
      " [0. 0. 0.]\n",
      " [0. 0. 0.]\n",
      " [0. 0. 0.]]\n",
      "[ 0.1  1.  10. ]\n",
      "[1.e-01 1.e+00 1.e+01 1.e+02 1.e+03]\n"
     ]
    }
   ],
   "source": [
    "accuracy_ss = np.matrix(np.zeros(shape=(5,3)),float)\n",
    "gamma_ss = np.logspace(-1,1,3)\n",
    "C_s = np.logspace(-1, 3, 5)# logspace(a,b,N)把10的a次方到10的b次方区间分成N份 \n",
    "print(accuracy_ss)\n",
    "print(gamma_ss)\n",
    "print(C_s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "C= 0.1 and gamma= 0.1:accuracy=0.7415158371040724\n",
      "C= 0.1 and gamma= 1.0:accuracy=0.7665643180349063\n",
      "C= 0.1 and gamma= 10.0:accuracy=0.49725274725274726\n",
      "C= 1.0 and gamma= 0.1:accuracy=0.7672107304460246\n",
      "C= 1.0 and gamma= 1.0:accuracy=0.807207498383969\n",
      "C= 1.0 and gamma= 10.0:accuracy=0.6755817711700065\n",
      "C= 10.0 and gamma= 0.1:accuracy=0.7914511958629605\n",
      "C= 10.0 and gamma= 1.0:accuracy=0.8205397543632837\n",
      "C= 10.0 and gamma= 10.0:accuracy=0.687863606981254\n",
      "C= 100.0 and gamma= 0.1:accuracy=0.8141564318034906\n",
      "C= 100.0 and gamma= 1.0:accuracy=0.8110859728506787\n",
      "C= 100.0 and gamma= 10.0:accuracy=0.6860859728506787\n",
      "C= 1000.0 and gamma= 0.1:accuracy=0.8066418875242405\n",
      "C= 1000.0 and gamma= 1.0:accuracy=0.8005817711700065\n",
      "C= 1000.0 and gamma= 10.0:accuracy=0.6843891402714932\n"
     ]
    }
   ],
   "source": [
    "for i,oneC in enumerate(C_s):\n",
    "    for j,gamma in enumerate(gamma_ss):\n",
    "        tmp = fit_grid_point_RBF(oneC,gamma,X_train_part,y_train_part,X_test_part,y_test_part)\n",
    "        accuracy_ss[i,j] = tmp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10.0\n",
      "1.0\n"
     ]
    }
   ],
   "source": [
    "### 最佳超参数\n",
    "index = np.unravel_index(np.argmax(accuracy_ss, axis=None), accuracy_ss.shape)\n",
    "Best_C = C_s[ index[0] ]\n",
    "Best_gamma = gamma_ss[ index[1] ]\n",
    "\n",
    "print(Best_C)\n",
    "print(Best_gamma)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "# SVC训练SVC，支持概率输出\n",
    "Best_C = 10\n",
    "Best_gamma = 1.0\n",
    "\n",
    "SVC4 =  SVC( C = Best_C, kernel='rbf', gamma = Best_gamma, probability=True)\n",
    "SVC4.fit(X_train, y_train)\n",
    "\n",
    "#保持模型，用于后续测试\n",
    "import pickle\n",
    "pickle.dump(SVC4, open(\"Otto_RBF_SVC.pkl\", 'wb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
